package com.universest.swordholder.viewmodel

import android.net.Uri
import androidx.compose.runtime.mutableStateListOf
import androidx.lifecycle.viewModelScope
import com.universest.swordholder.data.dao.Book
import com.universest.swordholder.data.dao.Passage
import com.universest.swordholder.data.getUserDb
import com.universest.swordholder.data.repository.BookRepository
import com.universest.swordholder.data.repository.LongTextRepository
import com.universest.swordholder.data.repository.PassageRepository
import com.universest.swordholder.data.repository.VolumeRepository
import com.universest.swordholder.model.NovelImporter
import com.universest.swordholder.task.AbstractTask
import com.universest.swordholder.task.NeedPrepareTask
import com.universest.swordholder.task.Task
import com.universest.swordholder.tools.UriFile
import com.universest.swordholder.tools.numberToChineseForShort
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.firstOrNull
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch

class WorksViewModel : BaseViewModel() {

    enum class WorksType {
        ALL,
        BOOK,
        SINGLE_PASSAGE
    }

    private var _filterWorksType = MutableStateFlow<WorksType>(WorksType.ALL)

    val filterWorksType = _filterWorksType.asStateFlow()

    val bookRepository = BookRepository(getUserDb())

    val passageRepository = PassageRepository(getUserDb())

    val volumeRepository = VolumeRepository(getUserDb())

    val longTextRepository = LongTextRepository(getUserDb())

    val allBooks = bookRepository.getAllBooks()

    private val _tasks = mutableStateListOf<AbstractTask<*, *>>()

    val tasks: List<AbstractTask<*, *>>
        get() = _tasks

    val books = combine(allBooks, _filterWorksType) { books, currentType ->
        books.filter { book ->
            when (currentType) {
                WorksType.ALL -> true
                WorksType.BOOK -> !book.singlePassage
                WorksType.SINGLE_PASSAGE -> book.singlePassage
            }
        }
    }
    fun setFilterWorksType(worksType: WorksType) {
        _filterWorksType.value = worksType
    }

    private fun generateBookDescription(book: Book): Flow<String> {
        if (book.singlePassage) {
            return bookRepository.getBookById(book.bookId).map { bookResult ->
                bookResult?.let {
                    "单章 ${numberToChineseForShort(it.charCount)}字"
                } ?: "无内容"
            }
        }
        val passageCount = passageRepository.getPassageCountByBookId(book.bookId)
        return combine(passageCount,bookRepository.getBookById(book.bookId)) {
            count,book ->
            if (count > 0 && book != null) {
                "共${count}章 ${numberToChineseForShort(book.charCount)}字"
            } else {
                "无内容"
            }
        }
    }

    private val bookDescriptionFlowMap: MutableMap<Int, StateFlow<String>> = mutableMapOf()

    @Synchronized
    fun getBookDescription(book: Book): StateFlow<String> {
        return bookDescriptionFlowMap.getOrPut(book.bookId) {
            generateBookDescription(book).stateIn(viewModelScope,SharingStarted.Lazily, "")
        }
    }

    fun createNewBook(bookName:String,bookDescription:String,singlePassage: Boolean){
        val book = Book(bookName = bookName, bookDescription = bookDescription, singlePassage = singlePassage)
        viewModelScope.launch {
            bookRepository.addBook(book)
            if(singlePassage){
                passageRepository.insert(Passage(bookId = book.bookId, title = bookName))
            }
        }
    }

    fun updateBook(book: Book){
        viewModelScope.launch {
            bookRepository.updateBook(book)
        }
    }

    suspend fun handleTxtFileImport(uri: Uri): Result<Unit>{
        val file = UriFile(uri)
        val task = NovelImporter(file).createTask()
        _tasks.add(task)
        val result = task.execute(Unit)
        _tasks.remove(task)
        return result
    }

    fun removeBook(bookId:Int){
        viewModelScope.launch {
            removeBookSuspend(bookId)
        }
    }

    private suspend fun removeBookSuspend(bookId:Int){
        val removeTask = NeedPrepareTask<Unit, Unit>("删除书籍", prepareTask = Task("获取书籍信息"){
            val passages = passageRepository.getPassagesByBookId(bookId).firstOrNull()?:emptyList()
            val volumes = volumeRepository.getVolumeByBookId(bookId).firstOrNull()?:emptyList()
            Task("删除中", progressMaxValue = passages.size + volumes.size + 1){
                var count = 0;
                for (passage in passages) {
                    longTextRepository.deleteById(passage.contentId)
                    longTextRepository.deleteById(passage.simpleContentId)
                    passageRepository.delete(passage)
                    count++
                    updateProgress(count, passages.size + volumes.size + 1)
                }
                for (volume in volumes) {
                    volumeRepository.delete(volume)
                    count++
                    updateProgress(count, passages.size + volumes.size + 1)
                }
                bookRepository.deleteBookById(bookId)
                count++
                updateProgress(count, passages.size + volumes.size + 1)
            }
        })
        _tasks.add(removeTask)
        removeTask.execute(Unit)
        _tasks.remove(removeTask)
    }

}